package no.sachmuld.methodcombination.demo;

import com.fasterxml.jackson.databind.ObjectMapper;
import no.sachmuld.methodcombination.api.MethodInvocation;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.List;

/**
 *
 */
public class RestFilterBehaviour <T extends Entity> extends FilterBehaviour {

    private Repository<T> repository;
    private Class<T> entityClass;

    public RestFilterBehaviour(Repository<T> repository, Class<T> entityClass) {
        this.repository = repository;
        this.entityClass = entityClass;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, MethodInvocation<Void> methodInvocation) throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        Long id = id(httpServletRequest.getServletPath());
        String method = httpServletRequest.getMethod();

        if ("POST".equals(method)) {
            if (id == null) {

                String json = input(httpServletRequest);

                ObjectMapper mapper = new ObjectMapper();

                T entity = mapper.readValue(json, entityClass);

                Entity inserted = repository.insert(entity);

                httpServletResponse.setStatus(HttpServletResponse.SC_CREATED);
                httpServletResponse.setContentType("text/plain");
                httpServletResponse.getWriter().println("Entity created with id:" + inserted.getId());

            } else {

                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);

            }
        } else if ("GET".equals(method)) {
            if (id == null) {

                List<T> all = repository.selectAll();

                ObjectMapper mapper = new ObjectMapper();
                String json = mapper.writer().writeValueAsString(all);

                httpServletResponse.setStatus(HttpServletResponse.SC_OK);
                httpServletResponse.setContentType("text/plain");
                httpServletResponse.getWriter().println(json);

            } else {

                T entity = repository.select(id);

                if (entity == null) {
                    httpServletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
                } else {

                    ObjectMapper mapper = new ObjectMapper();
                    String json = mapper.writer().writeValueAsString(entity);

                    httpServletResponse.setStatus(HttpServletResponse.SC_OK);
                    httpServletResponse.setContentType("text/plain");
                    httpServletResponse.getWriter().println(json);
                }
            }
        } else if ("PUT".equals(method)) {
            if (id == null) {

                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);

            } else {

                String json = input(httpServletRequest);

                ObjectMapper mapper = new ObjectMapper();

                T entity = mapper.readValue(json, entityClass);

                repository.update(entity);

                httpServletResponse.setStatus(HttpServletResponse.SC_OK);

            }
        } else if ("DELETE".equals(method)) {
            if (id == null) {

                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);

            } else {

                repository.delete(id);

                httpServletResponse.setStatus(HttpServletResponse.SC_OK);

            }
        } else {
            httpServletResponse.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        }

    }

    private Long id(String servletPath) {
        String sub = servletPath.substring(1);
        int idx = sub.indexOf('/');
        if (idx == -1) {
            return null;
        } else {
            String id = sub.substring(idx + 1);
            if (id.length() == 0) {
                return null;
            } else {
                return Long.parseLong(id);
            }
        }
    }
    private String input(HttpServletRequest request) throws IOException {
        StringBuilder builder = new StringBuilder();
        String line;
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
        return builder.toString();
    }
}
